package controlmercancias.gui.administracion;

import controlmercancias.dominio.Usuario;
import controlmercancias.gui.WaitingJFrame;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.awt.event.WindowEvent;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

import controlmercancias.remoto.servidortren.AdminListener;
import controlmercancias.remoto.servidortren.ServidorTren;
import controlmercancias.remoto.servidortren.ServidorTrenDemon;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.BorderFactory;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;

/**
 * @author Gonzalo
 * 
 */
public class Administrador extends JFrame implements AdminListener {

    private String administrador;
    private JTable tablaUsuarios;
    private JButton desconectar;
    private JButton añadir;
    private JButton modificar;
    private JButton eliminar;
    private JTextField numConexiones;
    private JButton setConexiones;
    private final String[] cabecera = new String[]{"Usuario", "Conectado"};
    private HashMap<Usuario, ServidorTren> conectados;
    private DefaultTableCellRenderer tableCellRenderer = new DefaultTableCellRenderer() {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            if (column == 1) {
                JPanel jp = new JPanel(new FlowLayout(FlowLayout.CENTER));
                jp.setBackground(super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, 0).getBackground());
                jp.setBorder(BorderFactory.createEmptyBorder(-5, -5, -5, -5));
                JCheckBox check = new JCheckBox("", (Boolean) value);
                jp.add(check);
                return jp;
            }
            return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        }
    };

    public Administrador(final AdminServerGUI servergui, String admin) {
        administrador = admin;
        this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        this.setLayout(new BorderLayout());
        this.setTitle("Administración de usuarios");
        this.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                super.windowClosing(e);
                ServidorTrenDemon.logOutAdmin();
                servergui.setVisible(true);
            }
        });
        init();
        JPanel botonera = getNorth();
        JPanel tabla = getTabla();
        add(tabla, BorderLayout.CENTER);
        add(botonera, BorderLayout.NORTH);
        desconectar.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                int row = tablaUsuarios.getSelectedRow();
                if (row == -1) {
                    JOptionPane.showMessageDialog(Administrador.this, "Selecciona un usuario para desconectarlo", "Seleccionar usuario", JOptionPane.WARNING_MESSAGE);
                    return;
                }
                Usuario user = (Usuario) tablaUsuarios.getValueAt(row, 0);
                if (!((Boolean) tablaUsuarios.getValueAt(row, 1))) {
                    JOptionPane.showMessageDialog(Administrador.this, "El usuario " + user.getNombre() + " no está conectado", "Seleccionar usuario", JOptionPane.WARNING_MESSAGE);
                    return;
                }
                ServidorTren userSt = conectados.get((Usuario) tablaUsuarios.getValueAt(row, 0));
                int op = JOptionPane.showConfirmDialog(Administrador.this, "¿Estás seguro de que quieres desconectar a " + userSt + "?", "Confirmación de desconexión", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
                if (op == JOptionPane.YES_OPTION) {
                    ServidorTrenDemon.expulsarUser(userSt);
                    refresh();
                }
            }
        });
        añadir.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                FormularioAdministrador f = new FormularioAdministrador(null, false);
                f.setVisible(true);
                refresh();
            }
        });
        modificar.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                int row = tablaUsuarios.getSelectedRow();
                if (row == -1) {
                    JOptionPane.showMessageDialog(Administrador.this, "Selecciona un usuario para modificarlo", "Seleccionar usuario", JOptionPane.WARNING_MESSAGE);
                    return;
                }
                Usuario user = (Usuario) tablaUsuarios.getValueAt(row, 0);
                FormularioAdministrador f = new FormularioAdministrador(user, (Boolean) tablaUsuarios.getValueAt(row, 1));//DONE Poner la linea de la tabla...
                f.setVisible(true);
                refresh();
            }
        });
        eliminar.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                int row = tablaUsuarios.getSelectedRow();
                if (row == -1) {
                    JOptionPane.showMessageDialog(Administrador.this, "Selecciona un usuario para eliminarlo", "Seleccionar usuario", JOptionPane.WARNING_MESSAGE);
                    return;
                }
                Usuario user = (Usuario) tablaUsuarios.getValueAt(row, 0);
                if (user.getNombre().equals(administrador)) {
                    JOptionPane.showMessageDialog(Administrador.this, "No te puedes eliminar a ti mismo", "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }
                int op = JOptionPane.showConfirmDialog(Administrador.this, "¿Estás seguro de que quieres eliminar a " + user + "?", "Confirmación de eliminación", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
                if (op == JOptionPane.YES_OPTION) {
                    if ((Boolean) tablaUsuarios.getValueAt(row, 1)) {
                        ServidorTrenDemon.expulsarUser(conectados.get(user));
                    }
                    ServidorTrenDemon.getAccesoDatos().deleteUsuario(user);
                    refresh();
                }
            }
        });
        setConexiones.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                int i = 0;
                try {
                    i = Integer.parseInt(numConexiones.getText());
                    if (i <= 0) {
                        throw new NumberFormatException();
                    }
                } catch (NumberFormatException ex) {
                    JOptionPane.showMessageDialog(Administrador.this, "El máximo de conexiones no es válido, debe ser un número mayor que 1", "Conexiones", JOptionPane.ERROR_MESSAGE);
                    numConexiones.requestFocus();
                    numConexiones.setSelectionStart(0);
                    numConexiones.setSelectionEnd(numConexiones.getText().length());
                    return;
                }
                ServidorTrenDemon.setMaxConnections(i);
            }
        });
        ServidorTrenDemon.logInAdmin(this);
        this.setSize(600, 400);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        this.setIconImage(ServidorTrenDemon.appIcon);
        refresh();
    }

    private void init() {
        conectados = new HashMap<Usuario, ServidorTren>();
        tablaUsuarios = new JTable(new DefaultTableModel(cabecera, 0)) {

            private static final long serialVersionUID = 1L;

            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
        tablaUsuarios.setRowHeight(20);
        tablaUsuarios.setAutoCreateRowSorter(true);
        tablaUsuarios.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
        tablaUsuarios.setColumnSelectionAllowed(false);
        tablaUsuarios.setDragEnabled(false);
        desconectar = new JButton("Desconectar");
        añadir = new JButton("Añadir");
        modificar = new JButton("Modificar");
        eliminar = new JButton("Eliminar");
        numConexiones = new JTextField(5);
        setConexiones = new JButton("Establecer máximo");
    }

    private JPanel getNorth() {
        JPanel north = new JPanel(new BorderLayout());
        JPanel botonera = new JPanel(new FlowLayout(FlowLayout.CENTER));
        botonera.add(desconectar);
        botonera.add(añadir);
        botonera.add(modificar);
        botonera.add(eliminar);
        north.add(botonera, BorderLayout.NORTH);

        JPanel conexiones = new JPanel(new FlowLayout(FlowLayout.LEFT));
        conexiones.add(new JLabel("Número máximo de conexiones:"));
        conexiones.add(numConexiones);
        conexiones.add(setConexiones);
        north.add(conexiones);
        return north;
    }

    private JPanel getTabla() {
        JPanel tabla = new JPanel(new GridLayout(1, 1));
        tabla.setBorder(BorderFactory.createTitledBorder(""));
        JScrollPane jsp = new JScrollPane(tablaUsuarios, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        tabla.add(jsp);
        return tabla;
    }

    @Override
    public void refresh() {
        final WaitingJFrame w = new WaitingJFrame("Actualizando usuarios...");
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                w.setVisible(true);
            }
        });
        new Thread(new Runnable() {

            @Override
            public void run() {
                conectados.clear();
                List<ServidorTren> connectedSt = ServidorTrenDemon.getConnectedUsers();
                List<Usuario> connectedUsers = new ArrayList<Usuario>(connectedSt.size());
                for (int i = 0; i < connectedSt.size(); i++) {
                    connectedUsers.add(connectedSt.get(i).getUsuarioActual());
                    conectados.put(connectedSt.get(i).getUsuarioActual(), connectedSt.get(i));
                }
                List<Usuario> allUsuarios = ServidorTrenDemon.getAccesoDatos().getAllUsuario();
                allUsuarios.removeAll(connectedUsers);
                DefaultTableModel dtl = new DefaultTableModel(cabecera, 0);
                for (int i = 0; i < connectedUsers.size(); i++) {
                    Usuario u = connectedUsers.get(i);
                    if (u != null) {
                        dtl.addRow(new Object[]{u, true});
                    }
                }
                for (int i = 0; i < allUsuarios.size(); i++) {
                    Usuario u = allUsuarios.get(i);
                    if (u != null) {
                        dtl.addRow(new Object[]{u, false});
                    }
                }
                tablaUsuarios.setModel(dtl);
                tablaUsuarios.getColumnModel().getColumn(1).setCellRenderer(tableCellRenderer);
                tablaUsuarios.getTableHeader().setReorderingAllowed(false);
                numConexiones.setText(ServidorTrenDemon.getMaxConnections() + "");
                w.setVisible(false);
                w.setEnabled(false);
                w.dispose();
            }
        }).start();
    }
}
